﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Studio7i.CapaPersistencia;
using Studio7i.CapaDominio;

namespace Studio7i.CapaNegocio
{
    public class ClienteServiceImpl : IClienteService
    {
        #region Dependencias
        IClienteDAO ClienteDAO = null;
        ISalaDAO SalaDAO = null;
        IReservaDAO ReservaDAO = null;
        IArmadoReservaDAO ArmadoReservaDAO = null;
        IInstrumentoDAO InstrumentoDAO = null;
        IServicioDAO ServicioDAO = null;
        #endregion

        #region Operaciones de negocio
        public Cliente RegistrarCliente(int codigo, string nombres, string email,string fechaNacimiento, string clave1, string clave2)
        {
            // Excepción si falta algún dato requerido
            if (codigo == 0 || nombres == null || email == null || fechaNacimiento == null || clave1 == null || clave2 == null)
                throw new DatosInsuficientesException("Faltan datos para crear el cliente");

            // Excepción si los ingresos de claves no coinciden
            if (clave1!=clave2)
                throw new DatosNoCoincidanException("Las clave no coinciden");           
                
            // Excepción si ya se registró el mismo cliente (por codigo o email de cliente)
            ICollection<Cliente> clientesEncontradosxCodigo = ClienteDAO.ListarXBusquedaCliente(codigo, null, null, null, null);
            ICollection<Cliente> clientesEncontradosxEmail = ClienteDAO.ListarXBusquedaCliente(null, null, email, null, null);
            if (clientesEncontradosxCodigo.Count > 0)
                throw new EntidadRepetidaException("El cliente ya existe con el mismo codigo");
            if (clientesEncontradosxEmail.Count > 0)
                throw new EntidadRepetidaException("Ya existe un cliente con el mismo correo");

            // Creación del cliente
            Cliente clienteACrear = new Cliente();
            clienteACrear.CoCliente = codigo;
            clienteACrear.NoCliente = nombres;
            clienteACrear.TxMail = email;
            clienteACrear.FeNacimiento = fechaNacimiento;
            clienteACrear.TxtClave = clave1;
            return ClienteDAO.Crear(clienteACrear);
        }
        public Reserva RegistrarReserva(string feinicio, string fefinal, decimal ssreserva, int codigoSala, int codigoCliente)
        {
            // Excepción si falta algún dato requerido
            if (feinicio == null || fefinal == null ||
                ssreserva == 0 || codigoSala == 0 || codigoCliente == 0)
                throw new DatosInsuficientesException("Faltan datos para crear la reserva");
            // Excepción si ya se registró la misma reserva (por sala y fechahora)
            Sala salaExistente = SalaDAO.Obtener(codigoSala);
            Cliente clienteExistente = ClienteDAO.Obtener(codigoCliente);
            ICollection<Reserva> reservasEncontradas = ReservaDAO.ListarXBusqueda(0, feinicio, null, 0, salaExistente, null);
            if (reservasEncontradas.Count > 0)
                throw new EntidadRepetidaException("La reserva ya existe");
            // Creación de la reserva
            Reserva reservaACrear = new Reserva();
            reservaACrear.FeInicio = feinicio;
            reservaACrear.FeFinal = fefinal;
            reservaACrear.SsReserva = ssreserva;
            reservaACrear.Sala = salaExistente;
            reservaACrear.Cliente = clienteExistente;
            return ReservaDAO.Crear(reservaACrear);
        }
        public ArmadoDeReserva RegistrarArmadoReserva(int armresCodigo, decimal ssarmado, int codigoReserva, int codigoInstrumento, int codigoServicios)
        {
            // Excepción si falta algún dato requerido
            if (armresCodigo == 0 ||
                ssarmado == 0 || codigoReserva == 0 || codigoInstrumento == 0 || codigoServicios == 0)
                throw new DatosInsuficientesException("Faltan datos para crear Armado Reserva");
            Reserva reservaExistente = ReservaDAO.Obtener(codigoReserva);
            Instrumento instrumentoExistente = InstrumentoDAO.Obtener(codigoInstrumento);
            Servicio servicioExistente = ServicioDAO.Obtener(codigoServicios);
            ICollection<ArmadoDeReserva> armadoreservasEncontradas = ArmadoReservaDAO.ListarXBusqueda(armresCodigo, 0, reservaExistente, instrumentoExistente, null);
            if (armadoreservasEncontradas.Count > 0)
                throw new EntidadRepetidaException("el armado de reserva ya existe");
            // Creación del armado de reserva
            ArmadoDeReserva armadoreservaACrear = new ArmadoDeReserva();
            armadoreservaACrear.SsArmado = ssarmado;
            armadoreservaACrear.Reserva = reservaExistente;
            armadoreservaACrear.Instrumento = instrumentoExistente;
            return ArmadoReservaDAO.Crear(armadoreservaACrear);
        }
        public ICollection<Sala> BusquedaDeSala(string nombreSala, string nombreLocal, string guitarra, string teclado, int? capacidad, string grabacion, string fechaHoraDisponible)
        {   
            ICollection<Sala> salasEncontradas= SalaDAO.ListarXFiltroBusquedaSala(nombreSala, nombreLocal,  guitarra,  teclado, capacidad, grabacion, fechaHoraDisponible);

            //Excepción si el resultado es vacio
            if (salasEncontradas.Count == 0)            
                throw new ResultadoVacioException("No se encontró nunguna sala");
            
            // Busqueda de la Sala OK
            return salasEncontradas;
        }
        #endregion

        #region Métodos de soporte para entidad Cliente
        public Cliente ObtenerCliente(int codigo)
        {
            return ClienteDAO.Obtener(codigo);
        }
        public ICollection<Cliente> ListarClientes()
        {
            return ClienteDAO.ListarTodos();
        }
        public ICollection<Cliente> ListarClientesXNombre(string nombre)
        {
            return ClienteDAO.ListarXNombre(nombre);
        }
        public ICollection<Cliente> ListarClienteXBusqueda(int? codigo, string nombres, string email, string fechaNacimiento, string clave)
        {
            return ClienteDAO.ListarXBusquedaCliente(codigo, nombres,email,fechaNacimiento,clave);
        } 
        #endregion

        #region Métodos de soporte para entidad Reserva
        public Reserva CrearReserva(Reserva reservaACrear)
        {
            ICollection<Reserva> existentes = ReservaDAO.ListarXBusqueda(null, reservaACrear.FeInicio, null, 0, reservaACrear.Sala, null);
            if (existentes.Count > 0)
                throw new EntidadRepetidaException("Reserva ya existente");
            return ReservaDAO.Crear(reservaACrear);
        }
        public Reserva ObtenerReserva(int codigo)
        {
            return ReservaDAO.Obtener(codigo);
        }
        public Reserva ModificarReserva(Reserva reservaAModificar)
        {
            return ReservaDAO.Modificar(reservaAModificar);
        }
        public void EliminarReserva(Reserva reservaAEliminar)
        {
            ReservaDAO.Eliminar(reservaAEliminar);
        }
        public ICollection<Reserva> ListarReservas()
        {
            return ReservaDAO.ListarTodos();
        }
        public ICollection<Reserva> ListarReservaBusqueda(int? reservaCodigo, string feinicio, string fefinal, decimal? ssreserva, int? salaCodigo, int? clienteCodigo)
        {
            Sala salaExistente = null;
            if (salaCodigo != null && salaCodigo != 0)
                salaExistente = SalaDAO.Obtener(salaCodigo.Value);
            return ReservaDAO.ListarXBusqueda(null, feinicio, null, 0, salaExistente, null);
        }
        #endregion

        #region Métodos de soporte para entidad ArmadoReserva
        public ArmadoDeReserva CrearArmadoReserva(ArmadoDeReserva armadoreservaACrear)
        {
            ICollection<ArmadoDeReserva> existentes = ArmadoReservaDAO.ListarXBusqueda(armadoreservaACrear.CoArmRes, 0, null, null, null);
            if (existentes.Count > 0)
                throw new EntidadRepetidaException("Armado de Reserva ya existente");
            return ArmadoReservaDAO.Crear(armadoreservaACrear);
        }
        public ArmadoDeReserva ObtenerArmadoReserva(int codigo)
        {
            return ArmadoReservaDAO.Obtener(codigo);
        }
        public ArmadoDeReserva ModificarArmadoReserva(ArmadoDeReserva armadoreservaAModificar)
        {
            return ArmadoReservaDAO.Modificar(armadoreservaAModificar);
        }
        public void EliminarArmadoReserva(ArmadoDeReserva armadoreservaAEliminar)
        {
            ArmadoReservaDAO.Eliminar(armadoreservaAEliminar);
        }
        public ICollection<ArmadoDeReserva> ListarArmadoReservas()
        {
            return ArmadoReservaDAO.ListarTodos();
        }
        public ICollection<ArmadoDeReserva> ListarArmadoReservaBusqueda(int? ArmRescodigo, decimal? ssarmado, int? instrumentoCodigo, int? servicioCodigo, int? reservaCodigo)
        {
            Instrumento instrumentoExistente = null;
            if (instrumentoCodigo != null && instrumentoCodigo != 0)
                instrumentoExistente = InstrumentoDAO.Obtener(instrumentoCodigo.Value);
            return ArmadoReservaDAO.ListarXBusqueda(null, 0, null, instrumentoExistente, null);
        }
        #endregion
    }
}